The approaches described in this section are approaches that could be pursued, but not necessarily approaches that have been previously conceived or pursued. Therefore, unless otherwise indicated, it should not be assumed that any of the approaches described in this section qualify as prior art merely by virtue of their inclusion in this section.
Cloud-based computer program applications may be built on backend services that expose an application interface (API) which serves data to a frontend, such as a user interface or other services. The backend services may connect to a data store, such as a relational database, that can be queried using a query language such as structured query language (SQL). The backend services interpret client requests, sends corresponding requests to a data store, and transforms the received data into a transport format according to the service's convention (e.g., XML or JSON).
Different end points may be implemented for specific information needs. However, writing and maintaining the code for each of these end points is a major cost driver in the development of a cloud-based application. In addition, as the information needs of the consumers change over time, changes in the conventions of the corresponding end points are required. If backward compatibility is desired, multiple versions of each end point's code must be maintained, which multiplies the maintenance cost.
Some existing frameworks, e.g. Spring, Struts, Hibernate, Ruby on Rails, simplify the generation of suitable requests to the datastore. For certain constrained use cases, such as Create, Read, Update or Delete (CRUD) services, the automatic generation of end point code is possible. However, generic storage and generated CRUD services provide poor performance compared to manually configured storage and coded end points. Typically, a person designing the backend services uses knowledge about the anticipated usage patterns and data volume to optimize the backend, while the generated CRUD services are unable to be optimized based on anticipated usage patterns and data volume. Furthermore, CRUD services are unable to efficiently handle complex queries spanning multiple entities.
One possible solution is to expose fewer end points, each with more powerful query capabilities. To maximize flexibility, the data store's query language could be directly exposed to the frontend services. However, this approach is not viable because 1) security considerations prohibit sending queries directly from the client to the data store; 2) queries may get too long and complicated; and 3) any changes in the data store would cause the consuming applications to cease to function.
Another possible approach is to use single end points with a high-level universal query language that is decoupled from the internal data store representation. They may expose metadata describing the types of objects, attributes and relations between objects, which allows the API convention to be stable even when information in the data store needs to change. Only the metadata returned by the API changes, and the consumers can often dynamically adapt to this. This approach may be implemented on generic data stores using, for example, Metaweb's Freebase and MQL language and SAP's HANA Graph which exposes the GEM language. Since these stores have no predefined schema for specific object types, the translation between high-level queries and the data store can be generic. However, generic data stores have disadvantages such as higher cost and/or lower performance compared to conventional databases.
Another high-level query language is Graph QL. However, Graph QL needs to be mapped to a pre-defined schema by means of code. Thus, while it shares the advantage of having a stable API, it still requires writing or re-writing code to establish or change a backend service. Also, Graph QL cannot express aggregations such as sums, averages, and counts, which means that any aggregations that may be required must be pre-defined and implemented in backend code.
Thus, a solution that does not require choosing between well-performing backends at the cost of developing, testing and deploying code and having limited flexibility with respect to the possible queries, or flexible, data-driven generic backends that can't handle complex analytical queries while maintaining good performance is desired.